package org.agile2soft.nexoma.tapestry.services.security;
//Copyright 2008 Thiago H. de Paula Figueiredo
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


import java.util.List;

import org.agile2soft.nexoma.core.controllers.UserController;
import org.agile2soft.nexoma.core.entities.InternalUser;
import org.slf4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.providers.dao.SaltSource;
import org.springframework.security.providers.encoding.PasswordEncoder;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;


/**
 * {@link UserDetailsService} using generic-authentication.
 *
 * @author Thiago H. de Paula Figueiredo
 */
public class UserDetailsServiceImpl2 implements UserDetailsService {

    /**
     * Obligatory suffix used in authority names by Acegi.
     */
    public static final String ACEGI_AUTHORITY_NAME_SUFFIX = "ROLE_";

    private UserController userController;

    private boolean allowSimultaneousLogins;

    /**
     * For a given permission name, returns the authority (permission) created to Acegi by
     * {@link #loadUserByUsername(String)}. It is
     * <code>ACEGI_AUTHORITY_NAME_SUFFIX + permission.toUpperCase()</code>.
     *
     * @param permissionName a {@link String}. It cannot be null.
     * @return a {@link String}.
     */
    public static String authorityName(String permissionName) {

        assert permissionName != null;
        return ACEGI_AUTHORITY_NAME_SUFFIX + permissionName.toUpperCase();

    }

    /**
     * Single constructor of this class.
     *
     * @param userController an {@link UserController}. It cannot be null.
     */
    public UserDetailsServiceImpl2(UserController userController, boolean allowSimultaneousLogins) {

        if (userController == null) {
            throw new IllegalArgumentException("Parameter userController cannot be null");
        }

        this.userController = userController;
        this.allowSimultaneousLogins = allowSimultaneousLogins;

    }

    public UserDetailsServiceImpl2(PasswordEncoder encoder, SaltSource salt,
            Logger logger, UserController userController) {
    }

    /**
     * @see org.acegisecurity.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
     */
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,
            DataAccessException {

        InternalUser user = userController.findById(username);

        if (user == null) {
            throw new UsernameNotFoundException("User " + username + " not found.");
        }

        return createUserDetails(user);

    }

    /**
     * Used by {@link #loadUserByUsername(String)} to creates and returns an {@link UserDetails}
     * instance for a giver {@link User}.
     *
     * @param user an {@link User}. It cannot be null.
     * @return an {@link UserDetails}.
     */
    protected UserDetails createUserDetails(InternalUser user ) {

        MyUserDetailsImpl userDetails = null;

        final String login = user.getLogin();
        final boolean enabled = true ; //user.isEnabled();
        final String password = user.getPassword();
        final boolean expired = false; // user.isExpired();
        final boolean credentialsExpired = false; //user.isCredentialsExpired();
        final boolean locked = false ; // user.isLocked() || (allowSimultaneousLogins == false && user.isLoggedIn());

        userDetails.addAuthority(new GrantedAuthorityImpl(authorityName(user.getProfile().getName())));

        return userDetails;

    }

}
